package org.fast.cms.security;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.fast.cms.common.domain.response.JsonResponse;
import org.fast.cms.common.enums.MessageCodeEnum;
import org.fast.cms.common.utils.string.StringUtils;
import org.fast.cms.domain.admin.response.user.User;
import org.fast.cms.entity.admin.SysUser;
import org.fast.cms.utils.UserUtils;
import org.fast.cms.utils.ValidateCodeServlet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import lombok.extern.slf4j.Slf4j;


/** 
* @author weigen.ye 
* @date 创建时间：2017年6月17日 下午12:30:19 
*
*/
@Slf4j
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

	public static final String DEFAULT_MESSAGE_PARAM = "message";

	private static final SerializerFeature[] feature = new SerializerFeature[] { SerializerFeature.WriteMapNullValue,
			SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullListAsEmpty,
			SerializerFeature.QuoteFieldNames, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.SortField };

	@Override
	protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
//		AdminAppProperties properties = SpringUtils.getBean(AdminAppProperties.class);
		String username = getUsername(request);
		String password = getPassword(request);
		boolean rememberMe = isRememberMe(request);
		if (StringUtils.isEmpty(username)) {
			throw new AuthenticationException("msg:请输入用户名");
		}
		if (StringUtils.isEmpty(password)) {
			throw new AuthenticationException("msg:请输入密码");
		}
		String validateCode = getValidateCode(request);
		log.error("token create");
		
		SysUser user = UserUtils.getByLoginName(username);
		if (user == null) {
			throw new AuthenticationException("msg:用户账户不存在");
		}
		if (user.getIsActivated() != 1) {
			throw new AuthenticationException("msg:用户账户未激活");
		}
		
	    /*
	     * 密码不加密，SystemAuthorizingRealm在调用doGetAuthenticationInfo会进行加密，
	     * SystemAuthorizingRealm继承的AuthenticatingRealm类的assertCredentialsMatch方法
	     * 会调用RetryLimitHashedCredentialsMatcher的doCredentialsMatch方法进行登录信息验证 
	     */
		return new UsernamePasswordToken(username,
				password,
				validateCode,rememberMe);
		
//		return new UsernamePasswordToken(username,
//				CryptUtils.encryptMode(password, properties.getPassword()),
//				validateCode,rememberMe);
	}


	private String getValidateCode(ServletRequest request) {
		return org.apache.shiro.web.util.WebUtils.getCleanParam(request, ValidateCodeServlet.VALIDATE_CODE);
	}

	/**
	 * 访问被拒(如果未登录跳转到登录，已登录情况下，跳转到未授权url，或者 401)
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		log.debug("Attempting to access a path which requires authentication.  Forwarding to the "
				+ "Authentication url [" + getLoginUrl() + "]");
		return super.onAccessDenied(request, response);
	}

	/**
	 * 登录成功
	 * 
	 * @param token
	 * @param subject
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
			ServletResponse response) throws Exception {
		JsonResponse<User> ret = new JsonResponse<User>(MessageCodeEnum.SUCCESS.getCode(), "登入成功");
		ret.setData(UserUtils.getUser());
		response.setCharacterEncoding("UTF-8");
	    response.setContentType("application/json; charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println(JSON.toJSONString(ret, feature));
		out.flush();
		out.close();
		return false;
	}

	/**
	 * 登录失败
	 * 
	 * @param token
	 * @param e
	 * @param request
	 * @param responseo
	 * @return
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request,
			ServletResponse response) {
		log.error("login failure");
		// return super.onLoginFailure(token, e, request, response);
		String className = e.getClass().getName(), message = "";
		if (IncorrectCredentialsException.class.getName().equals(className)
				|| UnknownAccountException.class.getName().equals(className)) {
			message = "用户名或密码错误，请重新输入！";
		} else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) {
			message = StringUtils.replace(e.getMessage(), "msg:", "");
		}

		else {
			message = "系统出现点问题，请稍后再试！";
			e.printStackTrace(); // 输出到控制台
		}
		JsonResponse<Void> json = new JsonResponse<Void>(MessageCodeEnum.FAILED.getCode(), message);
		response.setCharacterEncoding("UTF-8");
	    response.setContentType("application/json; charset=utf-8");
		try {
			PrintWriter out = response.getWriter();
			out.println(JSON.toJSONString(json));
			out.flush();
			out.close();
		} catch (IOException e1) {
		}
		return false;
	}
}
